package me.chan.netty.rpc.server.serialize;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

public class JSONSerializer  implements Serializer {

    private static Gson gson;

    static {
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(Class.class, new ClassCodec());
        gson = builder.create();
    }

    @Override
    public <T> byte[] serialize(T t) throws IOException {

        String json = gson.toJson(t);
        return json.getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public <T> T deserialize(Class<T> clazz, byte[] bytes) throws IOException {
        return gson.fromJson(new String(bytes, StandardCharsets.UTF_8), clazz);
    }


    /**
     *  serialize: Class --> String
     *  deserialize: String --> Class
     */
    static class ClassCodec implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {

        @Override
        public Class<?> deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
            String className = jsonElement.getAsString();
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new JsonParseException(e);
            }
        }

        @Override
        public JsonElement serialize(Class<?> aClass, Type type, JsonSerializationContext jsonSerializationContext) {

            return new JsonPrimitive(aClass.getName());
        }
    }

    public static void main(String[] args) {
        System.out.println(gson.toJson(String.class));
    }
}
